﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework.DataTable;
using UnityGameFramework.Runtime;

namespace TowerDefence_Zombie.Data
{
    public sealed class DataLevel : DataBase
    {
        private IDataTable<DRLevel> dtLevel;
        private Dictionary<int, LevelData> dicLevelData;

        private IDataTable<DRTreasureBox> dtTreasureBox;
        private Dictionary<int, TreasureBoxData> dicTreasureBoxData;

        public EnumLevelState LevelState
        {
            get;
            private set;
        }

        public Level CurrentLevel
        {
            get;
            set;
        }

        public int CurrentLevelIndex
        {
            get;
            set;
        }

        public int MaxLevel
        {
            get;
            private set;
        }

        protected override void OnPreload()
        {
            LoadDataTable("Level");
            LoadDataTable("TreasureBox");
        }

        protected override void OnLoad()
        {
            MaxLevel = 0;

            dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
            if (dtLevel == null)
                throw new System.Exception("Can not get data table Level");

            dicLevelData = new Dictionary<int, LevelData>();

            dtTreasureBox = GameEntry.DataTable.GetDataTable<DRTreasureBox>();
            if (dtTreasureBox == null)
                throw new System.Exception("Can not get data table TreasureBox");

            dicTreasureBoxData = new Dictionary<int, TreasureBoxData>();
            foreach (var dRTreasureBox in dtTreasureBox.GetAllDataRows())
                dicTreasureBoxData.Add(dRTreasureBox.Id, new TreasureBoxData(dRTreasureBox));

            DataWave dataWave = GameEntry.Data.GetData<DataWave>();
            if (dataWave == null)
                throw new System.Exception("Can not get data 'DataWave'");

            DRLevel[] dRLevels = dtLevel.GetAllDataRows();
            foreach (var dRLevel in dRLevels)
            {
                TreasureBoxData treasureBoxData = null;
                if (dRLevel.TreasureBoxId != 0 && dicTreasureBoxData.TryGetValue(dRLevel.TreasureBoxId, out treasureBoxData))
                {
                    //Debug.Log($"第{dRLevel.Id} 关 添加宝箱信息：{treasureBoxData.TreasureBoxId}");
                }
                SceneData sceneData = GameEntry.Data.GetData<DataScene>().GetSceneData(dRLevel.SceneId);

                int[] waveIds = dRLevel.WaveIds;
                WaveData[] waveDatas = new WaveData[waveIds.Length];
                for (int i = 0; i < waveIds.Length; i++)
                {
                    WaveData waveData = dataWave.GetWaveData(waveIds[i]);
                    if (waveData == null)
                        throw new System.Exception("Can not find Wave Data id :" + waveIds[i]);

                    waveDatas[i] = waveData;
                }

                LevelData levelData = new LevelData(dRLevel, waveDatas, sceneData, treasureBoxData);
                dicLevelData.Add(dRLevel.Id, levelData);

                if (dRLevel.Id > MaxLevel)
                    MaxLevel = dRLevel.Id;
            }
        }

        public void SwitchLevel(int level, Level levelCtrl)
        {
            CurrentLevelIndex = level;
            CurrentLevel = levelCtrl;
        }

        public void ChangeLevelState(EnumLevelState targetLevelState)
        {
            if (LevelState == targetLevelState)
                return;

            if (GetLevelData(CurrentLevelIndex, out var levelData) == false)
            {
                Log.Error("Can not found level '{0}.'", CurrentLevelIndex);
                return;
            }

            EnumLevelState lastLevelState = LevelState;
            LevelState = targetLevelState;
            GameEntry.Event.Fire(this, LevelStateChangeEventArgs.Create(levelData, lastLevelState, LevelState));
            Log.Debug("Current level is '{0}',level state is '{1}.'", levelData.Name, LevelState.ToString());
        }

        public bool GetLevelData(int index, out LevelData data)
        {
            return dicLevelData.TryGetValue(index, out data);
        }

        public bool IsMaxLevel(int levelIndex)
        {
            return levelIndex >= MaxLevel;
        }

        protected override void OnUnload()
        {
            GameEntry.DataTable.DestroyDataTable<DRLevel>();
        }

        public void TryGetTreasureBoxData(int treasureBoxId, out TreasureBoxData data)
        {
            dicTreasureBoxData.TryGetValue(treasureBoxId, out data);
        }


        public bool TryGetTowerIsUnLock(int towerId)
        {
            LevelData levelData = GetLevelData(CurrentLevelIndex, out var data) ? data : null;
            if (levelData == null)
                return false;
            else
            {
                for (int i = 0; i < levelData.AllowTowers.Length; i++)
                {
                    if (levelData.AllowTowers[i] == towerId)
                        return true;
                }
            }
            return false;
        }
    }
}